from flask_restful import Resource, marshal
from sqlalchemy import or_, desc, func

from app.exception import APIException, USER_NOT_EXISTS, BANNER_NOT_EXISTS, BRANCH_NOT_EXISTS, BRAND_NOT_EXISTS, \
    CATEGORY_NOT_EXISTS, GOODS_NOT_EXISTS, ORDER_NOT_EXISTS, DATABASE_ERROR, BRAND_NOT_NULL, CATEGORY_NOT_NULL, \
    USERNAME_OR_PHONE_IS_EXISTS
from app.api.admin.fields import admin_user_fields, banner_fields, branch_fields, brand_fields, user_fields, \
    category_fields, order_fields, goods_fields, explain_fields
from app.api.admin.parsers import update_admin_user_args, get_param_parser, pagination_parser, add_admin_user_args, \
    admin_user_filter_parser, update_banner_args, add_banner_args, update_branch_args, branch_filter_parser, \
    add_branch_args, update_brand_args, add_brand_args, filter_parser, sort_parser, update_category_args, \
    add_category_args, add_order_args, update_order_args, add_goods_args, update_goods_args, user_filter_parser, \
    order_filter_parser, date_filter_parser, goods_filter_parser, add_explain_args
from app.extensions import roles_accepted, auth, db
from app.models import AdminUser, Banner, Branch, Brand, User, Category, Order, Goods, GoodsPicture, Explain


class AdminUserResource(Resource):
    methods = ['OPTIONS', 'GET', 'PUT', 'DELETE']
    decorators = [roles_accepted('super', 'admin', 'user'), auth.login_required]

    @staticmethod
    def user_exist(user_id):
        user = AdminUser.query.get(user_id)
        if not user:
            # abort(404, message='用户(id=%s)不存在' % user_id, code=404)
            raise APIException(USER_NOT_EXISTS)
        return user

    def get(self, user_id):
        """ 获取用户信息 """
        user = self.user_exist(user_id)
        return {
            'code': 0,
            'message': '',
            'data': marshal(user, admin_user_fields)
        }, 200

    def put(self, user_id):
        # if g.user.role != 'admin' and g.user.id != user_id:
        #     raise APIException(403, '没有权限')
        user = self.user_exist(user_id)
        args = update_admin_user_args.parse_args()
        password = args.pop('password')
        if password:
            user.set_password(password)
        user.update(True, **args)
        return {
            'code': 0,
            'message': '更新成功',
            'data': marshal(user, admin_user_fields)
        }, 200

    def delete(self, user_id):
        user = self.user_exist(user_id)

        user.update(True, deleted=1)
        return {
            'code': 0,
            'message': '删除成功'
        }, 200


class AdminUsersResource(Resource):
    methods = ['GET', 'OPTIONS', 'POST']
    decorators = [roles_accepted('super', 'admin'), auth.login_required]

    def get(self):
        args = get_param_parser.parse_args()

        query = AdminUser.query

        _filter = args.get('filter')
        if _filter:
            filter_args = admin_user_filter_parser.parse_args(req=args)
            keyword = filter_args.pop('keyword')
            if keyword:
                query = query.filter(
                    or_(AdminUser.username.like("%" + keyword + "%"), AdminUser.real_name.like("%" + keyword + "%")))
            else:
                for k, v in filter_args.items():
                    if v is not None:
                        query = query.filter(getattr(AdminUser, k).like("%" + v + "%"))

        page_args = pagination_parser.parse_args(req=args)
        page = page_args.get('page')
        per_page = page_args.get('per_page')

        _users = query.paginate(page, per_page=per_page, error_out=False)
        # if page > _users.pages:
        #     abort(400, message="page no can't max than pages, no users data!",
        #           error_date=fmt_date(datetime.datetime.now()))
        # if not _users.items:
        #     abort(404, message="no users data!", error_date=fmt_date(datetime.datetime.now()))

        users = {
            'data': marshal(_users.items, admin_user_fields),
            "pageSize": _users.per_page,
            "pageNo": _users.page,
            "totalPage": _users.pages,
            "totalCount": _users.total
        }

        return {
            'code': 0,
            'message': '',
            'data': users
        }, 200

    def post(self):
        args = add_admin_user_args.parse_args()

        username = args.get('username')
        phone_number = args.get('phone_number')
        user = AdminUser.query.filter(db.or_(AdminUser.phone_number == phone_number, AdminUser.username == username)).first()
        if user:
            raise APIException(USERNAME_OR_PHONE_IS_EXISTS)
        user = AdminUser.create(**args)

        return {
            'code': 0,
            'message': '创建成功',
            'data': marshal(user, admin_user_fields)
        }, 201


class BannerResource(Resource):
    methods = ['OPTIONS', 'GET', 'PUT', 'DELETE']
    decorators = [roles_accepted('super', 'admin', 'user'), auth.login_required]

    @staticmethod
    def banner_exist(banner_id):
        banner = Banner.query.get(banner_id)
        if not banner:
            raise APIException(BANNER_NOT_EXISTS)
        return banner

    def get(self, banner_id):
        """ 获取轮播图信息 """
        banner = self.banner_exist(banner_id)
        return {
            'code': 0,
            'message': '',
            'data': marshal(banner, banner_fields)
        }, 200

    def put(self, banner_id):
        banner = self.banner_exist(banner_id)
        args = update_banner_args.parse_args()
        banner.update(True, **args)
        return {
           'code': 0,
           'message': '更新成功',
           'data': marshal(banner, banner_fields)
        }, 200

    def delete(self, banner_id):
        banner = self.banner_exist(banner_id)

        # banner.update(True, deleted=1)
        banner.delete()
        return {
           'code': 0,
           'message': '删除成功'
        }, 200


class BannersResource(Resource):
    methods = ['GET', 'OPTIONS', 'POST']
    decorators = [roles_accepted('super', 'admin'), auth.login_required]

    def get(self):
        args = get_param_parser.parse_args()

        query = Banner.query

        page_args = pagination_parser.parse_args(req=args)
        page = page_args.get('page')
        per_page = page_args.get('per_page')

        _banners = query.paginate(page, per_page=per_page, error_out=False)

        banners = {
            'data': marshal(_banners.items, banner_fields),
            "pageSize": _banners.per_page,
            "pageNo": _banners.page,
            "totalPage": _banners.pages,
            "totalCount": _banners.total
        }

        return {
           'code': 0,
           'message': '',
           'data': banners
        }, 200

    def post(self):
        args = add_banner_args.parse_args()

        banner = Banner.create(**args)

        return {
           'code': 0,
           'message': '创建成功',
           'data': marshal(banner, banner_fields)
        }, 201


class BranchResource(Resource):
    methods = ['OPTIONS', 'GET', 'PUT', 'DELETE']
    decorators = [roles_accepted('super', 'admin', 'user'), auth.login_required]

    @staticmethod
    def branch_exist(branch_id):
        branch = Branch.query.get(branch_id)
        if not branch:
            raise APIException(BRANCH_NOT_EXISTS)
        return branch

    def get(self, branch_id):
        branch = self.branch_exist(branch_id)
        return {
           'code': 0,
           'message': '',
           'data': marshal(branch, branch_fields)
        }, 200

    def put(self, branch_id):
        branch = self.branch_exist(branch_id)
        args = update_branch_args.parse_args()
        branch.update(True, **args)

        return {
           'code': 0,
           'message': '更新成功',
           'data': marshal(branch, branch_fields)
        }, 200

    def delete(self, branch_id):
        branch = self.branch_exist(branch_id)
        branch.update(True, deleted=1)
        return {
           'code': 0,
           'message': '删除成功'
        }, 200


class BranchesResource(Resource):
    methods = ['GET', 'OPTIONS', 'POST']
    decorators = [roles_accepted('super', 'admin'), auth.login_required]

    def get(self):
        args = get_param_parser.parse_args()

        query = Branch.query

        _filter = args.get('filter')
        if _filter:
            filter_args = branch_filter_parser.parse_args(req=args)
            keyword = filter_args.pop('keyword')
            if keyword:
                query = query.filter(
                    or_(Branch.name.like("%" + keyword + "%"), Branch.manager.like("%" + keyword + "%")))
            else:
                for k, v in filter_args.items():
                    if v is not None:
                        query = query.filter(getattr(Branch, k).like("%" + v + "%"))

        page_args = pagination_parser.parse_args(req=args)
        page = page_args.get('page')
        per_page = page_args.get('per_page')

        _branches = query.paginate(page, per_page=per_page, error_out=False)

        branches = {
            'data': marshal(_branches.items, branch_fields),
            "pageSize": _branches.per_page,
            "pageNo": _branches.page,
            "totalPage": _branches.pages,
            "totalCount": _branches.total
        }

        return {
           'code': 0,
           'message': '',
           'data': branches
        }, 200

    def post(self):
        args = add_branch_args.parse_args()

        branch = Branch.create(**args)

        return {
           'code': 0,
           'message': '创建成功',
           'data': marshal(branch, branch_fields)
        }, 201


class BrandResource(Resource):
    methods = ['OPTIONS', 'GET', 'PUT', 'DELETE']
    decorators = [roles_accepted('super', 'admin', 'user'), auth.login_required]

    @staticmethod
    def brand_exist(brand_id):
        brand = Brand.query.get(brand_id)
        if not brand:
            raise APIException(BRAND_NOT_EXISTS)
        return brand

    def get(self, brand_id):
        brand = self.brand_exist(brand_id)
        return {
           'code': 0,
           'message': '',
           'data': marshal(brand, brand_fields)
        }, 200

    def put(self, brand_id):
        brand = self.brand_exist(brand_id)
        args = update_brand_args.parse_args()
        brand.update(True, **args)

        return {
           'code': 0,
           'message': '更新成功',
           'data': marshal(brand, brand_fields)
        }, 200

    def delete(self, brand_id):
        brand = self.brand_exist(brand_id)
        goods = Goods.query.filter_by(brand_id=brand_id).all()
        if goods > 0:
            raise APIException(BRAND_NOT_NULL)
        brand.delete()
        return {
           'code': 0,
           'message': '删除成功'
        }, 200


class BrandsResource(Resource):
    methods = ['GET', 'OPTIONS', 'POST']
    decorators = [roles_accepted('super', 'admin'), auth.login_required]

    def get(self):
        args = get_param_parser.parse_args()

        query = Brand.query.filter(Brand.deleted == 0)

        _sort = args.get('sort')
        if _sort:
            sort_args = sort_parser.parse_args(req=args)
            field = getattr(Brand, sort_args.get('field'))
            if sort_args.get('reverse'):
                field = desc(field)
            query = query.order_by(field)

        page_args = pagination_parser.parse_args(req=args)
        page = page_args.get('page')
        per_page = page_args.get('per_page')

        _brands = query.paginate(page, per_page=per_page, error_out=False)

        brands = {
            'data': marshal(_brands.items, brand_fields),
            "pageSize": _brands.per_page,
            "pageNo": _brands.page,
            "totalPage": _brands.pages,
            "totalCount": _brands.total
        }

        return {
           'code': 0,
           'message': '',
           'data': brands
        }, 200

    def post(self):
        args = add_brand_args.parse_args()

        brand = Brand.create(**args)

        return {
           'code': 0,
           'message': '创建成功',
           'data': marshal(brand, brand_fields)
        }, 201


class CategoryResource(Resource):
    methods = ['OPTIONS', 'GET', 'PUT', 'DELETE']
    decorators = [roles_accepted('super', 'admin', 'user'), auth.login_required]

    @staticmethod
    def category_exist(category_id):
        category = Category.query.get(category_id)
        if not category:
            raise APIException(CATEGORY_NOT_EXISTS)
        return category

    def get(self, category_id):
        category = self.category_exist(category_id)
        return {
           'code': 0,
           'message': '',
           'data': marshal(category, category_fields)
        }, 200

    def put(self, category_id):
        category = self.category_exist(category_id)
        args = update_category_args.parse_args()
        category.update(True, **args)

        return {
           'code': 0,
           'message': '更新成功',
           'data': marshal(category, category_fields)
        }, 200

    def delete(self, category_id):
        category = self.category_exist(category_id)
        # category.update(True, deleted=1)
        # 判断分类下是否有商品
        goods = Goods.query.filter_by(category_id=category_id).all()
        if goods:
            raise APIException(CATEGORY_NOT_NULL)
        category.delete(True)
        return {
           'code': 0,
           'message': '删除成功'
        }, 200


class CategoriesResource(Resource):
    methods = ['GET', 'OPTIONS', 'POST']
    decorators = [roles_accepted('super', 'admin'), auth.login_required]

    def get(self):
        args = get_param_parser.parse_args()

        query = Category.query

        query = query.order_by(desc(Category.sort))

        page_args = pagination_parser.parse_args(req=args)
        page = page_args.get('page')
        per_page = page_args.get('per_page')

        _categories = query.paginate(page, per_page=per_page, error_out=False)

        categories = {
            'data': marshal(_categories.items, category_fields),
            "pageSize": _categories.per_page,
            "pageNo": _categories.page,
            "totalPage": _categories.pages,
            "totalCount": _categories.total
        }

        return {
           'code': 0,
           'message': '',
           'data': categories
        }, 200

    def post(self):
        args = add_category_args.parse_args()

        category = Category.create(**args)

        return {
           'code': 0,
           'message': '创建成功',
           'data': marshal(category, category_fields)
        }, 201


class GoodsResource(Resource):
    methods = ['OPTIONS', 'GET', 'PUT', 'DELETE']
    decorators = [roles_accepted('super', 'admin', 'user'), auth.login_required]

    @staticmethod
    def goods_exist(goods_id):
        goods = Goods.query.get(goods_id)
        if not goods:
            raise APIException(GOODS_NOT_EXISTS)
        return goods

    def get(self, goods_id):
        goods = self.goods_exist(goods_id)
        return {
           'code': 0,
           'message': '',
           'data': marshal(goods, goods_fields)
        }, 200

    def put(self, goods_id):
        goods = self.goods_exist(goods_id)
        args = update_goods_args.parse_args()

        images = args.pop('images')

        goods.update(False, **args)

        if images:
            for image in images:
                if image.get('id'):
                    pic = GoodsPicture.query.get(image.get('id'))
                    if image.get('deleted'):
                        pic.delete(False,)
                    else:
                        pic.update(False, **image)
                else:
                    image['goods_id'] = goods.id
                    GoodsPicture.create(False, **image)

        try:
            db.session.commit()
        except Exception as e:
            db.session.rollback()
            raise APIException(DATABASE_ERROR)

        return {
           'code': 0,
           'message': '更新成功',
           'data': marshal(goods, goods_fields)
        }, 200

    def delete(self, goods_id):
        goods = self.goods_exist(goods_id)
        goods.update(True, deleted=1)
        return {
           'code': 0,
           'message': '删除成功'
        }, 200


class GoodsListResource(Resource):
    methods = ['GET', 'OPTIONS', 'POST']
    decorators = [roles_accepted('super', 'admin'), auth.login_required]

    def get(self):
        args = get_param_parser.parse_args()

        query = Goods.query.filter_by(deleted=0)

        _filter = args.get('filter')
        if _filter:
            filter_args = goods_filter_parser.parse_args(req=args)
            name = filter_args.pop('name')
            if name:
                query = query.filter(Goods.name.like('%' + name + '%'))
            for k, v in filter_args.items():
                if v is not None:
                    query = query.filter(getattr(Goods, k) == v)

        _sort = args.get('sort')
        if _sort:
            sort_args = sort_parser.parse_args(req=args)
            field = getattr(Goods, sort_args.get('field'))
            if sort_args.get('reverse'):
                field = desc(field)
            query = query.order_by(field)

        page_args = pagination_parser.parse_args(req=args)
        page = page_args.get('page')
        per_page = page_args.get('per_page')

        _goods = query.paginate(page, per_page=per_page, error_out=False)

        goods = {
            'data': marshal(_goods.items, goods_fields),
            "pageSize": _goods.per_page,
            "pageNo": _goods.page,
            "totalPage": _goods.pages,
            "totalCount": _goods.total
        }

        return {
           'code': 0,
           'message': '',
           'data': goods
        }, 200

    def post(self):
        args = add_goods_args.parse_args()

        images = args.pop('images')

        goods = Goods.create(False, **args)

        for image in images:
            image['goods_id'] = goods.id
            GoodsPicture.create(False, **image)

        try:
            db.session.commit()
        except Exception as e:
            db.session.rollback()
            raise APIException(DATABASE_ERROR)

        return {
           'code': 0,
           'message': '创建成功',
           'data': marshal(goods, goods_fields)
        }, 201


class OrderResource(Resource):
    methods = ['OPTIONS', 'GET', 'PUT', 'DELETE']
    decorators = [roles_accepted('super', 'admin', 'manager'), auth.login_required]

    @staticmethod
    def order_exist(order_id):
        order = Order.query.get(order_id)
        if not order:
            raise APIException(ORDER_NOT_EXISTS)
        return order

    def get(self, order_id):
        order = self.order_exist(order_id)
        return {
           'code': 0,
           'message': '',
           'data': marshal(order, order_fields)
        }, 200

    def put(self, order_id):
        order = self.order_exist(order_id)
        args = update_order_args.parse_args()
        order.update(True, **args)

        return {
           'code': 0,
           'message': '更新成功',
           'data': marshal(order, order_fields)
        }, 200

    def delete(self, order_id):
        order = self.order_exist(order_id)
        # order.update(True, deleted=1)
        order.delete(True)
        return {
           'code': 0,
           'message': '删除成功'
        }, 200


class OrdersResource(Resource):
    methods = ['GET', 'OPTIONS', 'POST']
    decorators = [roles_accepted('super', 'admin'), auth.login_required]

    def get(self):
        args = get_param_parser.parse_args()

        query = Order.query

        _filter = args.get('filter')
        if _filter:
            filter_args = order_filter_parser.parse_args(req=args)
            # order_no = filter_args.pop('order_no')
            # if order_no:
            #     query = query.filter(Order.order_no == order_no)

            for k, v in filter_args.items():
                if v is not None:
                    query = query.filter(getattr(Order, k) == v)

            date_filter_args = date_filter_parser.parse_args(req=args)
            start_date = date_filter_args.get('start_date')
            end_date = date_filter_args.get('end_date')
            if start_date:
                if end_date is None:
                    end_date = start_date
                query = query.filter((func.date(Order.order_time)).between(start_date, end_date))

        _sort = args.get('sort')
        if _sort:
            sort_args = sort_parser.parse_args(req=args)
            field = getattr(Order, sort_args.get('field'))
            if sort_args.get('reverse'):
                field = desc(field)
            query = query.order_by(field)

        page_args = pagination_parser.parse_args(req=args)
        page = page_args.get('page')
        per_page = page_args.get('per_page')

        _orders = query.paginate(page, per_page=per_page, error_out=False)

        orders = {
            'data': marshal(_orders.items, order_fields),
            "pageSize": _orders.per_page,
            "pageNo": _orders.page,
            "totalPage": _orders.pages,
            "totalCount": _orders.total
        }

        return {
           'code': 0,
           'message': '',
           'data': orders
        }, 200

    def post(self):
        args = add_order_args.parse_args()

        order = Order.create(**args)

        return {
           'code': 0,
           'message': '创建成功',
           'data': marshal(order, order_fields)
        }, 201


class UserResource(Resource):
    methods = ['OPTIONS', 'GET', 'PUT', 'DELETE']
    decorators = [roles_accepted('super', 'admin', 'user'), auth.login_required]

    def get(self, user_id):
        pass

    def put(self, user_id):
        pass

    def delete(self, user_id):
        pass


class UsersResource(Resource):
    methods = ['GET', 'OPTIONS', 'POST']
    decorators = [roles_accepted('super', 'admin', 'manager'), auth.login_required]

    def get(self):
        args = get_param_parser.parse_args()

        query = User.query

        _filter = args.get('filter')
        if _filter:
            filter_args = user_filter_parser.parse_args(req=args)
            uid = filter_args.pop('uid')
            if uid is not None:
                query = query.filter_by(uid=uid)
                user = query.first()
                if user:
                    return {
                       'code': 0,
                       'message': '',
                       'data': marshal(user, user_fields)
                    }, 200
                else:
                    raise APIException(USER_NOT_EXISTS)
            keyword = filter_args.pop('keyword')
            if keyword is not None:
                query = query.filter(
                    or_(User.nickname.like("%" + keyword + "%"), User.uid.like("%" + keyword + "%")))

        page_args = pagination_parser.parse_args(req=args)
        page = page_args.get('page')
        per_page = page_args.get('per_page')

        _users = query.paginate(page, per_page=per_page, error_out=False)

        users = {
            'data': marshal(_users.items, user_fields),
            "pageSize": _users.per_page,
            "pageNo": _users.page,
            "totalPage": _users.pages,
            "totalCount": _users.total
        }

        return {
           'code': 0,
           'message': '',
           'data': users
        }, 200

    def post(self):
        pass


class UserAddressResource(Resource):
    methods = ['OPTIONS', 'GET', 'PUT', 'DELETE']
    decorators = [roles_accepted('super', 'admin', 'user'), auth.login_required]

    def get(self, address_id):
        pass

    def put(self, address_id):
        pass

    def delete(self, address_id):
        pass


class UserAddressesResource(Resource):
    methods = ['GET', 'OPTIONS', 'POST']
    decorators = [roles_accepted('super', 'admin'), auth.login_required]

    def get(self):
        pass

    def post(self):
        pass


class ExplainResource(Resource):
    methods = ['OPTIONS', 'GET', 'PUT', 'DELETE']
    decorators = [roles_accepted('super', 'admin'), auth.login_required]

    def get(self, explain_id):
        """获取兑换说明信息"""
        pass

    def put(self, explain_id):
        """ 修改兑换说明信息 """
        pass

    def delete(self, explain_id):
        """ 删除兑换说明信息 """
        pass


class ExplainListResource(Resource):
    methods = ['GET', 'OPTIONS', 'POST']
    decorators = [roles_accepted('super', 'admin'), auth.login_required]

    def get(self):
        """ 获取兑换说明信息列表 """
        args = get_param_parser.parse_args()

        query = Explain.query

        page_args = pagination_parser.parse_args(req=args)
        page = page_args.get('page')
        per_page = page_args.get('per_page')

        _explain = query.paginate(page, per_page=per_page, error_out=False)

        explain = {
            'data': marshal(_explain.items, explain_fields),
            "pageSize": _explain.per_page,
            "pageNo": _explain.page,
            "totalPage": _explain.pages,
            "totalCount": _explain.total
        }

        return {
           'code': 0,
           'message': '',
           'data': explain
        }, 200

    def post(self):
        """ 添加兑换说明信息 """
        args = add_explain_args.parse_args()

        explain = Explain.create(**args)

        return {
           'code': 0,
           'message': '创建成功',
           'data': marshal(explain, explain_fields)
        }, 201
